#![feature(impl_trait_in_assoc_type)]

use colored::Colorize;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::zerocopy_channel::{self as channel, Channel};
use embassy_time::Timer;

#[embassy_executor::main]
async fn main(spawner: embassy_executor::Spawner) {
    const N: usize = 1;
    let buf = Box::into_raw(Box::new([0; N]) as Box<[_]>);

    let channel = Box::leak(Box::new(Channel::<'static, CriticalSectionRawMutex, _>::new(unsafe { &mut *buf })));
    let (sender, recv) = channel.split();

    spawner.spawn(consumer(recv)).unwrap();
    spawner.spawn(producer(sender)).unwrap(); // tasks start in reverse order
}

type Sender = channel::Sender<'static, CriticalSectionRawMutex, i32>;
type Receiver = channel::Receiver<'static, CriticalSectionRawMutex, i32>;

#[embassy_executor::task]
async fn producer(mut sender: Sender) {
    loop {
        let val = sender.send().await;
        println!("{}", format!("before send: val={val}").white());
        *val += 1;
        println!("{}", format!("[send] ++1 val={val}").green().bold());
        sender.send_done();
        Timer::after_secs(1).await;
    }
}

#[embassy_executor::task]
async fn consumer(mut receiver: Receiver) {
    loop {
        let val = receiver.receive().await;
        println!("{}", format!("recv: val={val}").blue().bold().on_white());
        *val += 2;
        println!("{}", format!("[recv] ++2 val={val}").white());
        receiver.receive_done();
        Timer::after_secs(1).await;
    }
}
